﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Xml;

namespace System.Security.Cryptography
{
    public class RSACrypt
    {
        public RSACrypt(string EncryptKey, string DecryptKey,string PublicModNumber)
        {
            if (EncryptKey != null)
                E = new BigInteger(EncryptKey, 16);
            if (DecryptKey != null)
                D = new BigInteger(DecryptKey, 16);

            N = new BigInteger(PublicModNumber, 16);
            maxbit = N.bitCount();
        }

        int maxbit;
        BigInteger E, D, N;

        public int MaxEncryptBits()
        {
            return maxbit;
        }
        public int MaxEncryptBytes()
        {
            return maxbit >> 3;
        }

        public string[] EncryptBase64Blocks(string data)
        {
            byte[] inarray = Encoding.Default.GetBytes(data);
            List<string> result = new List<string>();
            int maxbyte = MaxEncryptBytes();
            byte[] block = new byte[maxbyte];

            int i, j,n;
            for (i = 0, j = 0, n = inarray.Length; i < n; i++,j++)
            {
                if (j >= maxbyte)
                {
                    result.Add(EncryptBase64(block)); //encrypt, add to result
                    block = new byte[maxbyte];        //reset buffer
                    j = 0;                            //set pointer
                }

                block[j] = inarray[i];                //copy to buffer
            }
            if (j != 0 && j <= maxbyte)
                result.Add(EncryptBase64(block));

            return result.ToArray();
        }
        public string EncryptBase64(byte[] data)
        {
            byte[] result = Encrypt(data);
            return Convert.ToBase64String(result);
        }
        public string EncryptBase64(string data)
        {
            byte[] bytes = Encoding.Default.GetBytes(data);
            byte[] result = Encrypt(bytes);
            return Convert.ToBase64String(result);
        }
        public byte[] Encrypt(byte[] data)
        {
            if (E == null) throw new Exception("RSA密钥丢失");
            if ((data.Length << 3) > maxbit) throw new Exception("密钥长度不足");
            
            BigInteger M,C;

            M = new BigInteger(data);
            C = M.modPow(E, N);

            return C.getBytes();
        }

        public string DecryptBase64Blocks(string[] blocks)
        {
            byte[] data;
            StringBuilder sb = new StringBuilder();

            foreach (string i in blocks)
            {
                data = Convert.FromBase64String(i);
                sb.Append(DecryptString(data));
            }

            return sb.ToString();
        }
        public string DecryptString(byte[] data)
        {
            byte[] result = Decrypt(data);
            return Encoding.Default.GetString(result);
        }
        public byte[] Decrypt(byte[] data)
        {
            if (D == null) throw new Exception("密钥丢失");

            BigInteger M, C;

            C = new BigInteger(data);
            M = C.modPow(D, N);

            return M.getBytes();
        }

        public string EncryptBase64String(string data)
        {
            string[] result = this.EncryptBase64Blocks(data);
            StringBuilder sb = new StringBuilder();
            foreach (string i in result)
            {
                sb.Append(i);
                sb.Append(",");
            }
            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }
        public string DecryptBase64String(string data)
        {
            string[] rtv = data.Split(',');
            return this.DecryptBase64Blocks(rtv);
        }
    }
}